package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.sc.nft.admin.config.RefundMemberIdConfig;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.entity.SysMember;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.SysMemberPool;
import com.sc.nft.service.DeveloperBackstageService;
import com.sc.nft.service.ModifyPhoneNumberRecordsService;
import com.sc.nft.service.PayRefundService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/developerBackstage")
@Api(tags = "开发者后台")
public class DeveloperBackstageController {

    private final DeveloperBackstageService developerBackstageService;
    private final ModifyPhoneNumberRecordsService modifyPhoneNumberRecordsService;
    private final PayRefundService payRefundService;
    private final Redisson redisson;
    private final RefundMemberIdConfig refundMemberIdConfig;


    @PostMapping(value = "/refundOrderPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "退款订单列表", notes = "退款订单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<RefundOrderPageVO> refundOrderPage(@Valid @RequestBody RefundOrderPageDTO request) {
        return PageResult.success(developerBackstageService.refundOrderPage(request));
    }

    @PostMapping(value = "/tripartitePayRefoundList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "三方支付退款列表", notes = "三方支付退款列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<PayOrderVO>> tripartitePayRefundList(@Valid @RequestBody TripartitePayRefundListDTO request) {
        return Result.success(developerBackstageService.tripartitePayRefundList(request));
    }

    @PostMapping(value = "/userTelRecordPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "手机号列表", notes = "手机号列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserTelPageVO> userTelRecordPage(@RequestBody UserPhonePageVO request) {
        return PageResult.success(modifyPhoneNumberRecordsService.userTelRecordPage(request));
    }
    @PostMapping(value = "/refund", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "退款", notes = "退款", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result refund(@RequestBody RefundDTO request) {
        operationAuthority();
        String key = RedisKeyEnum.REFUND_LOCK.getKey() + request.getId();
        RLock lock = redisson.getLock(key);
        try {
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                developerBackstageService.refund(request);
            } else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    private void operationAuthority() {
        SysMember sysMember = SysMemberPool.getMember();
        if (BeanUtil.isEmpty(sysMember)) {
            throw new GlobalRunTimeException("用户未登录");
        }
        if (!refundMemberIdConfig.getId().contains(sysMember.getId())) {
            throw new GlobalRunTimeException("当前用户无权限操作");
        }
    }


    @PostMapping(value = "/userTelUpdateRecordUpdate", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "更改手机号", notes = "更改手机号", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result userTelUpdateRecordUpdate(@RequestBody ModifyPhoneNumberRecordsDTO request) {
        operationAuthority();
        RLock lock = redisson.getLock(RedisKeyEnum.MODIFY_USER_TEL.getKey() + request.getId());
        try{
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                modifyPhoneNumberRecordsService.userTelUpdateRecordUpdate(request);
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @PostMapping(value = "/userTelUpdateRecordPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "更改手机号记录分页列表", notes = "更改手机号记录分页列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<ModifyPhoneNumberRecordsPageVO> userTelUpdateRecordPage(@RequestBody ModifyPhoneNumberRecordsPageDTO request) {
        if(StrUtil.isBlank(request.getChangeAfterUserTel()) && StrUtil.isBlank(request.getChangeBeforeUserTel())){
            return PageResult.success();
        }
        return PageResult.success(modifyPhoneNumberRecordsService.userTelUpdateRecordPage(request));
    }

    @PostMapping(value = "/tripartitePayRefundRecordsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "三方支付退款记录列表", notes = "三方支付退款记录列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<PayRefundRecordsVO> tripartitePayRefundRecordsPage(@RequestBody PayRefundDTO request) {
        return PageResult.success(payRefundService.tripartitePayRefundRecordsPage(request));
    }

}
